﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using Nemerle.Imperative;
using System.Threading;


namespace FTClient
{
	/// <summary>
	/// Description of GlobalServer.
	/// </summary>
	class GlobalServer
	{
	    private static mutable serverName:string;
	    private static mutable serverPort:int;
	    private static mutable serverSocket:Socket=null;
	    public static mutable uid:string;
	    public static mutable fileList:List[oneFileInfo]=List();
	    
	    public static Refresh(name:string, port:int):void
	    {
	        serverName=name;
	        serverPort=port;
//	        serverSocket=GetSocket.ConnectSocket(name,port);
	    }
	    
	    private static SocketToS(sock:Socket):string
	    {
	        mutable str:string="(:IP \""+(sock.LocalEndPoint:>IPEndPoint).Address.ToString()+"\"";
	        
	        str=str+" :PORT "+(sock.LocalEndPoint:>IPEndPoint).Port.ToString()+")";
	        str;
	    }
	    
	    private static FileInfoToS(fileInfo:oneFileInfo):string
	    {
	        mutable str:string = "(:NAME \""+fileInfo.filename+"\"";
	        str = str+" :HASH "+fileInfo.hash.ToString()+")";
	        str;
	    }
	    private static SToFileInfo(str:string):oneFileInfo
	    {
	        mutable fileInfo=oneFileInfo();
	        fileInfo.filename=str.Substring(str.IndexOf('"')+1,str.LastIndexOf('"')-str.IndexOf('"')-1);
	        fileInfo.hash =Convert.ToInt32(str.Substring(str.IndexOf(":HASH ")+6,str.LastIndexOf(')')-str.IndexOf(":HASH ")-6));
	        fileInfo;
	    }
	    
	    private static SToConnection(str:string):Connection
	    {
	        mutable con=Connection("",0);
	        con.server=str.Substring(str.IndexOf('"')+1,str.LastIndexOf('"')-str.IndexOf('"')-1);
	        con.port=Convert.ToInt32(str.Substring(str.IndexOf(":PORT ")+6,str.LastIndexOf(')')-str.IndexOf(":PORT ")-6));
	        con;
	    }
	    
	    public static Connect(fileList:List[oneFileInfo], clientSocket:Socket):void
	    {
	        serverSocket=GetSocket.ConnectSocket(serverName,serverPort);
	        mutable messageString="";
	        messageString = "C\r("+SocketToS(clientSocket);
	        messageString = messageString+"(";
	        foreach (oneFile:oneFileInfo in fileList)
	        {
	            messageString=messageString+FileInfoToS(oneFile);
	        }
	        messageString = messageString+"))";
	        
	        // Высылаем запрос
	        _ = serverSocket.Send(Encoding.ASCII.GetBytes(messageString));
	        mutable buffer:array[Byte]=array(256);
	        _ = serverSocket.Receive(buffer);
	        uid=Encoding.ASCII.GetString(buffer).Trim('\0');
            serverSocket.Close();
//for test            uid="12345";
	    }
	    
	    public static Disconnect():void
	    {
 	        serverSocket=GetSocket.ConnectSocket(serverName,serverPort);

	        mutable messageString="D\r(:ID "+uid+")";
	        _ = serverSocket.Send(Encoding.ASCII.GetBytes(messageString));
            serverSocket.Close();

	    }
	    
	    public static Search(searchString:string):void
	    {
	        serverSocket=GetSocket.ConnectSocket(serverName,serverPort);

	        // Высылаем запрос
	        _ = serverSocket.Send(Encoding.ASCII.GetBytes("S\r("+searchString+")"));
	        
	        mutable buffer:array[Byte]=array(2000);
	        Thread.Sleep(1000);
	        _ = serverSocket.Receive(buffer);
	        mutable found=Encoding.ASCII.GetString(buffer).Trim('\0');
	        
            _ = fileList.Clear();
//	        mutable found="((:NAME \"input.txt\" :HASH 2480873)(:NAME \"file_name y\" :HASH 5322))";
            mutable str="";
            while (found.IndexOf(')')>1)
            {
                str=found.Remove(found.IndexOf(')')+1);
                found = found.Substring(found.IndexOf(')')+1);
                fileList.Add(SToFileInfo(str));
            }
            serverSocket.Close();            

	    }
	    
	    public static GetFileLocation(hash:int):Connection
	    {
	        serverSocket=GetSocket.ConnectSocket(serverName,serverPort);

	        def getString="G\r(:ID "+uid+" :HASH "+hash.ToString()+")";
	        _ = serverSocket.Send(Encoding.ASCII.GetBytes(getString));
	        mutable buffer:array[Byte]=array(256);
	        _ = serverSocket.Receive(buffer);
	        def respString=Encoding.ASCII.GetString(buffer).Trim('\0');
	        serverSocket.Close();
	        when (respString.Equals("E"))
	        {
	            return null;
	        }

//for test            def respString="(:IP \"192.168.0.1\" :PORT 2222)";
	        
            SToConnection(respString);
	    }
	    
	    
        public static VerifyDownload(hash:int,destUID:string):bool
        {
	        serverSocket=GetSocket.ConnectSocket(serverName,serverPort);

	        def verString="V\r(:ID "+destUID+" :HASH "+hash.ToString()+")";
	        _ = serverSocket.Send(Encoding.ASCII.GetBytes(verString));
	        mutable buffer:array[Byte]=array(256);
	        _ = serverSocket.Receive(buffer);
            serverSocket.Close();	       
	        def respString=Encoding.ASCII.GetString(buffer).Trim('\0');
	        when (respString.Equals("Y"))
	            return true;
	            
	        false;

//for test            true;	        
	        
	    }
/*	    public static ReDownload(hash:int):Connection
	    {
	        def getString="R\r"+hash.ToString();
	        _ = serverSocket.Send(Encoding.ASCII.GetBytes(getString));
	        mutable buffer:array[Byte]=array(256);
	        _ = serverSocket.Receive(buffer);
	        def respString=Encoding.ASCII.GetString(buffer).Trim('\0');
	        when (respString.Equals("E"))
	        {
	            return null;
	        }
            SToConnection(respString);
	    }
*/	    
	    public static FindHash(filename:string):int
	    {

	        foreach(fileInfo:oneFileInfo in fileList)
	        {
	            when (fileInfo.filename.Equals(filename))
	            {
	                return fileInfo.hash;
	            }
	        }
	        0;
	    }
	    
	    
	}
}
